/**
 * Copyright (c) 2015-2016, Javen Zhou  (javenlife@126.com).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package com.qlm.controller;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jfinal.aop.Clear;
import com.jfinal.core.Controller;
import com.jfinal.kit.HashKit;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.weixin.sdk.api.ApiConfig;
import com.jfinal.weixin.sdk.api.ApiConfigKit;
import com.jfinal.weixin.sdk.api.JsTicket;
import com.jfinal.weixin.sdk.api.JsTicketApi;
import com.jfinal.weixin.sdk.api.PaymentApi;
import com.jfinal.weixin.sdk.api.JsTicketApi.JsApiType;
import com.jfinal.weixin.sdk.api.PaymentApi.TradeType;
import com.jfinal.weixin.sdk.kit.IpKit;
import com.jfinal.weixin.sdk.kit.PaymentKit;
import com.jfinal.weixin.sdk.utils.JsonUtils;
import com.qlm.entity.Order;
import com.qlm.interceptor.WeixinController;
import com.qlm.service.ShopMgr;
import com.qlm.tool.WxUtil;

/**
 * 感谢 *半杯* 童鞋联调支付API
 * @author L.cm
 */
public class WeixinPayController extends WeixinController {
	
	static Logger logger = LoggerFactory.getLogger(WeixinPayController.class);
	//商户相关资料
	private static String appid = PropKit.get("appid");
	private static String partner = PropKit.get("paterner");
	private static String paternerKey = PropKit.get("partner_key");
	private static String notify_url = PropKit.get("authoUrl")+"/pay/pay_notify";
	
	public void index() {
		// openId，采用 网页授权获取 access_token API：SnsAccessTokenApi获取
		String openId = getOpenId();
		String id = getPara("id");
		Order o = Order.dao.findById(id);
		if(o == null){//没有就返回到订单中心
			logger.info("没有找到订单，返回到订单页面,订单号是 ："+id+",openid为:"+openId);
			redirect("/orderPage");
			return;
		}
		setAttr("order", o);
		// 统一下单文档地址：https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
		
		Map<String, String> params = new HashMap<String, String>();
		params.put("appid", appid);
		params.put("mch_id", partner);
		params.put("body", PropKit.get("detail"));
		params.put("out_trade_no", o.getStr("id"));
		String price  = o.getStr("price_");
		BigDecimal price_ = new BigDecimal(price);
		int p = price_.multiply(new BigDecimal(100)).intValue();
		params.put("total_fee", p+"");
		
		String ip = IpKit.getRealIp(getRequest());
		if (StrKit.isBlank(ip)) {
			ip = "127.0.0.1";
		}
		
		params.put("spbill_create_ip", ip);
		params.put("trade_type", TradeType.JSAPI.name());
		params.put("nonce_str", System.currentTimeMillis() / 1000 + "");
		params.put("notify_url", notify_url);
		params.put("openid", openId);

		String sign = PaymentKit.createSign(params, paternerKey);
		params.put("sign", sign);
		String xmlResult = PaymentApi.pushOrder(params);
		
		//System.out.println(xmlResult);形成订单的返回信息
		Map<String, String> result = PaymentKit.xmlToMap(xmlResult);
		
		String return_code = result.get("return_code");
		String return_msg = result.get("return_msg");
		logger.info("创建订单结果:"+return_msg+",return_code:"+return_code);
		if (StrKit.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
			redirect("/orderPage");
			return;
		}
		String result_code = result.get("result_code");
		if (StrKit.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
			String err_code = result.get("err_code");
			String err_code_des = result.get("err_code_des");
			logger.error("创建订单失败，结果为err_code:"+err_code+",err_code_desc:"+err_code_des);
			redirect("/orderPage");
			return;
		}
		// 以下字段在return_code 和result_code都为SUCCESS的时候有返回
		String prepay_id = result.get("prepay_id");
		
		Map<String, String> packageParams = new HashMap<String, String>();
		packageParams.put("appId", appid);
		String timeStamp = System.currentTimeMillis() / 1000 + "";
		packageParams.put("timeStamp", timeStamp);
		String nonceStr = System.currentTimeMillis() + "";
		packageParams.put("nonceStr", nonceStr);
		packageParams.put("package", "prepay_id=" + prepay_id);
		packageParams.put("signType", "MD5");
		String packageSign = PaymentKit.createSign(packageParams, paternerKey);
		packageParams.put("paySign", packageSign);
		
		String jsonStr = JsonUtils.toJson(packageParams);
		setAttr("json", jsonStr);
		setJsTicket();
		render("/shop/pay.jsp");
	}
	
	
	protected void setJsTicket() {
		ApiConfigKit.setThreadLocalApiConfig(getApiConfig());
		JsTicket jsApiTicket = JsTicketApi.getTicket(JsApiType.jsapi);
		String jsapi_ticket = jsApiTicket.getTicket();
		String nonce_str = create_nonce_str();
		// 注意 URL 一定要动态获取，不能 hardcode.
		String url = "http://" + getRequest().getServerName() // 服务器地址
				// + ":"
				// + getRequest().getServerPort() //端口号
				+ getRequest().getContextPath() // 项目名称
				+ getRequest().getServletPath();// 请求页面或其他地址
		String qs = getRequest().getQueryString(); // 参数
		if (qs != null) {
			url = url + "?" + (getRequest().getQueryString());
		}
		String timestamp = create_timestamp();
		// 这里参数的顺序要按照 key 值 ASCII 码升序排序
		//注意这里参数名必须全部小写，且必须有序
		String  str = "jsapi_ticket=" + jsapi_ticket +
        "&noncestr=" + nonce_str +
        "&timestamp=" + timestamp +
        "&url=" + url;
		String signature = HashKit.sha1(str);
		setAttr("appId", ApiConfigKit.getApiConfig().getAppId());
		setAttr("nonceStr", nonce_str);
		setAttr("timestamp", timestamp);
		setAttr("url", url);
		setAttr("signature", signature);
		setAttr("jsapi_ticket", jsapi_ticket);
	}
	
	private static String create_timestamp() {
		return Long.toString(System.currentTimeMillis() / 1000);
	}
	
	private static String create_nonce_str() {
		return UUID.randomUUID().toString();
	}
	
	public ApiConfig getApiConfig() {
		ApiConfig ac = new ApiConfig();
		// 配置微信 API 相关常量
		ac.setToken("qianlima");
		ac.setAppId("wxf8a19ee135d725a3");
		ac.setAppSecret("92857fb2be98d260d46bc1b4c8e10fd0");

		/**
		 * 是否对消息进行加密，对应于微信平台的消息加解密方式： 1：true进行加密且必须配置 encodingAesKey
		 * 2：false采用明文模式，同时也支持混合模式
		 */
		ac.setEncryptMessage(PropKit.getBoolean("encryptMessage", false));
		ac.setEncodingAesKey(PropKit.get("encodingAesKey",
				"setting it in config file"));
		return ac;
	}
	
	@Clear
	public void pay_notify() {
		// 支付结果通用通知文档: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
		String xmlMsg = HttpKit.readData(getRequest());
		System.out.println("支付通知="+xmlMsg);
		Map<String, String> params = PaymentKit.xmlToMap(xmlMsg);
		
		String result_code  = params.get("result_code");
		// 总金额
		String totalFee     = params.get("total_fee");
		// 商户订单号
		String orderId      = params.get("out_trade_no");
		// 微信支付订单号
		String transId      = params.get("transaction_id");
		// 支付完成时间，格式为yyyyMMddHHmmss
		String timeEnd      = params.get("time_end");
		
		// 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
		// 避免已经成功、关闭、退款的订单被再次更新
		
		if(PaymentKit.verifyNotify(params, paternerKey)){
			if (("SUCCESS").equals(result_code)) {
				//更新订单信息
				System.out.println("更新订单信息");
				
				Map<String, String> xml = new HashMap<String, String>();
				xml.put("return_code", "SUCCESS");
				xml.put("return_msg", "该订单已支付");
				Order o = Order.dao.findById(orderId);
				if(o != null){
					Integer status_ = WxUtil.getInt("status_", o);
					if(status_ == 0){
						Date d = new Date();
						SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
						try {
							d = sdf.parse(timeEnd);
						} catch (ParseException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						o.set("status_", 1).set("finish_time_", d).update();
						logger.info("账单支付成功");
					}
				}
				renderText(PaymentKit.toXml(xml));
				return;
			}
		}
		renderText("");
	}
}
